package nc.plugin;

import java.util.*;
import com.alibaba.fastjson.JSONArray;
import com.yonyou.ucf.mdf.util.HttpClientUtil;
import nc.bs.dao.BaseDAO;
import nc.bs.framework.common.NCLocator;
import nc.bs.itf.yfk.IBIPAttachService;
import nc.bs.itf.yfk.IYFKService;
import nc.itf.uap.busibean.ISysInitQry;
import nc.jdbc.framework.processor.ColumnProcessor;
import nc.jdbc.framework.processor.MapProcessor;
import nc.pubitf.para.SysInitQuery;
import nc.vo.gl.pubvoucher.VoucherVO;
import nc.vo.pub.BusinessException;
import com.alibaba.fastjson.JSONObject;
public class YFKHandlerUtil {
	private BaseDAO baseDAO;
	private IBIPAttachService bipAttachService;
	private IYFKService YFKService;
	private ISysInitQry sysInitQry;

    public static final String YFK_APP_KEY = "99a364240b4c454ba5a20e4b0d82e9f8";
    public static final String YFK_APP_SECRET = "dcbe1d681ef27f169cfbb201a55263f57d35f05d";

    public static final String YFK_DOMAIN_URL = "https://c3.yonyoucloud.com";
    public static final String YFK_PRINT_PDF_URL = "/iuap-api-gateway/yonbip/znbz/rbsm/api/bill/common/printbillpdf";
	/**
	 * 友费控发票上传NC65
	 * @param vo
	 * @throws BusinessException
	 */
	public static void YFKAttachToNC65Bill(VoucherVO vo) throws BusinessException{
		YFKHandlerUtil util = new YFKHandlerUtil();
		String pk_voucher = vo.getPk_voucher();
		int count = (int)util.getBaseDAO().executeQuery("select COUNT(*) from YFKATTACH_XLOG where PK_GLID = '"+pk_voucher+"' ", new ColumnProcessor());
		if(count > 0) return;
		// 1、获取当前发票是否与友费控有关联
		Map<String,Object> map = (Map<String,Object>)util.getBaseDAO().executeQuery(util.buildGLAndYFKBillRelevance(pk_voucher), new MapProcessor());
//		Map<String,Object> map = new HashMap<String,Object>();
//		map.put("lycode", "TYBX202502280426");
//		map.put("lybilltype", "RBSM010");
		if(map == null ||map.isEmpty()) return ;// 说明当前凭证不是来源单据生成及费控
		// 2、上传发票到NC65单据中
		List<JSONObject> attachs = util.getYFKAttachsByNCKey(pk_voucher, map);
		if(attachs == null || attachs.isEmpty()) return;
		String creator = vo.getCreator();
		util.getBIPAttachService().uploadAttachToBIPInputStream(pk_voucher, "", creator, attachs);
	}
	
	/**
	 * 构建NC65与友费控关联的SQL
	 * @return
	 * @throws BusinessException
	 */
	protected String buildGLAndYFKBillRelevance(String pk_voucher) throws BusinessException{
		StringBuilder sql = new StringBuilder();
		sql.append(" select ");
		sql.append("    fr.src_freedef1 lycode,fr.src_billtype lybilltype,fr.src_system lysystem,  ");
		sql.append("    fr.des_billtype mdbilltype,fr.des_freedef1,fr.des_system mdsystem,fr.des_busidate mdbusidate");
		sql.append(" from gl_voucher glv ");
		sql.append(" inner join fip_relation fr on glv.pk_voucher = fr.des_relationid ");
		sql.append(" where 1 = 1 and glv.dr = 0 and fr.dr = 0  ");
		sql.append("   and fr.des_billtype = 'C0' and fr.src_system in ('EM','FIP') ");// FIP代表费控
		sql.append("   and  glv.pk_voucher = '"+pk_voucher+"'"); 
		return sql.toString();
	}
	
	/**
	 * 获取友费控发票发票与附件信息
	 * @param pk_voucher NC65需要关联的单据PK
	 * @param map     当前数据为费控单据号及单据类型   
	 * @return        [{"attachmentPath":"httt://test.pdf","attachmentType":"pdf","attachmentName":"test"}]
	 * @throws BusinessException
	 */
	protected List<JSONObject> getYFKAttachsByNCKey(String pk_voucher,Map<String,Object> map) throws BusinessException{
		// 检查单据生成信息中单据信息是否缺失
		this.checkBillGenerate(map);
		// 获取单据查询和单据附件查询中的单据类型
		Object defCode = map.get("lybilltype");
		Map<String,Object> defMap = (Map<String,Object>)this.getBaseDAO().executeQuery(this.buildDefdocSQL(defCode, "YFKANDHRP01"), new MapProcessor());
		if(defMap == null || defMap.isEmpty()) throw new BusinessException("请在【自定义档案维护-全局】节点维护【单据生成】节点来源单据类型【"+defCode+"】对应的映射关系档案编码【YFKANDHRP01】");
		this.checkDefdocParam(defMap);
		String yfktbj = "http://"+SysInitQuery.getParaString("GLOBLE00000000000000", "YFKTBJ");
		// 1、获取友费控 accessToken
		String url = yfktbj+ "/yfkService/token";
		JSONObject tokenJson = new JSONObject();
		tokenJson.put("appKey", YFK_APP_KEY);
		tokenJson.put("appSecret", YFK_APP_SECRET);
        String accessToken = null;
        try {
            accessToken = HttpClientUtil.sendPost(url, tokenJson.toJSONString());
        } catch (Exception e) {
            throw new BusinessException("获取token异常:" + e.getMessage());
        }
        JSONObject queryParam = new JSONObject();
		queryParam.put("access_token", accessToken);
		Map<String,Object> bodyParam = new HashMap<>();
		// 单据类型(znbzbx_billmanage_busistriplist:出差申请类;znbzbx_billmanage_applylist:通用申请类;znbzbx_billmanage_travellist:差旅报销类;
		// znbzbx_billmanage_explist:通用报销类;znbzbx_billmanage_loanlist:借款类;znbzbx_billmanage_prepaylist:预付类;znbzbx_billmanage_holdlist:预提类;
		// znbzbx_billmanage_deferlist:摊销类;znbzbx_billmanage_returnlist:还款类;znbzbx_billmanage_refundlist:退款类)    示例: znbzbx_billmanage_applylist
		bodyParam.put("billnum", defMap.get("listtype")); // 单据类型
		bodyParam.put("pageSize", 5000); // 每页行数
		bodyParam.put("pageIndex", 0); // 页码
		bodyParam.put("code", map.get("lycode")); // 单据编号
		// 2、通过即将生成的凭证ID，关联友费控 单据查询 节点信息 中的对应的单据ID
		String queryBillList = yfktbj+ "/yfkService/queryYFLBillList";
		JSONObject billMap = new JSONObject();
		billMap.put("body", bodyParam);
		billMap.put("queryParam", queryParam);
		String resp ="";
		JSONObject yfkBillJSON = new JSONObject();
		try {
			resp = HttpClientUtil.sendPost(queryBillList, billMap.toString());
			if("".equals(resp) || resp == null){
				throw new BusinessException("查询友费控单据信息异常: " + resp);
			}
			yfkBillJSON = JSONObject.parseObject(resp);
        } catch (Exception e) {
            throw new BusinessException(e.getMessage());
        }
		// 使用 Jackson 将 byte[] 转换为 Map
        if(yfkBillJSON.isEmpty()) return null; //说明当前单据在友费控端未上传附件即附件
		// 3、通过单据ID去过去发票信息
		JSONObject attlparam = new JSONObject();
		// 单据类型 (znbzbx_memoapply:通用申请单;znbzbx_busistrip:出差申请单;znbzbx_expensebill:通用报销单;znbzbx_travelexpbill:差旅报销单) 
		attlparam.put("pk_billtype", defMap.get("attachtype"));// 单据类型
		attlparam.put("billID", yfkBillJSON.getString("id"));
		JSONObject attjson = new JSONObject();
		attjson.put("body", attlparam);
		attjson.put("queryParam", queryParam);
		String queryBillAttachURL = yfktbj+ "/yfkService/queryYFLBillAttachList";
		List<JSONObject> attachs = new ArrayList<>();
		try {
			resp = HttpClientUtil.sendPost(queryBillAttachURL, attjson.toString());
			if("".equals(resp) || resp == null){
				throw new BusinessException("获取单据附件信息异常: " + resp);
			}
			JSONArray arrs = JSONObject.parseArray(resp);
			for(Object json : arrs){
				attachs.add((JSONObject)json);
			}
		} catch (Exception e) {
			throw new BusinessException("查询友费控单据信息异常: " + e.getMessage());
		}

        // 4.获取友费控打印模板PDF
		String transferfUrl = yfktbj+ "/yfkService/queryYFLPrintBillPDF";
        JSONObject printPdfParam = new JSONObject();
        printPdfParam.put("pk_billtype", defMap.get("attachtype"));// 单据类型
        printPdfParam.put("billID", yfkBillJSON.getString("id")); // 单据ID
        printPdfParam.put("printTmplCode", defMap.get("printcode"));// 打印模板编码

		JSONObject pdfjson = new JSONObject();
		pdfjson.put("body", printPdfParam);
		pdfjson.put("queryParam", queryParam);
        try {
            // 发生请求
            resp = HttpClientUtil.sendPost(transferfUrl, JSONObject.toJSONString(pdfjson));
            if("".equals(resp) || resp == null){
                throw new BusinessException("获取单据打印PDF附件信息异常: " + resp);
            }
            JSONObject respJson = JSONObject.parseObject(resp);
            // 组装下载数据到attachs中
            if ("200".equals(respJson.get("code")) && respJson.get("data") != null && !"".equals(respJson.get("data"))) {
                String pdfUrl = respJson.get("data").toString();
                JSONObject pdfResult = new JSONObject();
                pdfResult.put("attachmentPath", pdfUrl);
                pdfResult.put("attachmentType", "pdf");
//                pdfResult.put("attachmentName", pdfUrl.substring(pdfUrl.lastIndexOf('/') + 1, pdfUrl.lastIndexOf('.')));
                pdfResult.put("attachmentName", "费用审批表");
                attachs.add(pdfResult);
            }else{
				throw new BusinessException("获取PDF异常: " + resp);
			}
        } catch (Exception e) {
            throw new BusinessException("获取单据打印PDF附件信息异常2: " + e.getMessage());
        }

		return attachs;
	}


	/**
	 * 检查单据生成节点 单据信息是否齐全
	 * @param map 通过凭证关联查询出来的 单据生成节点信息
	 * @throws BusinessException
	 */
	protected void checkBillGenerate(Map<String,Object> map) throws BusinessException{
		if(map.get("lycode") == null || "".equals(map.get("lycode"))) throw new BusinessException("由友费控系统生成的单据,在【单据生成】节点中来源单据号不允许为空!");
		if(map.get("lybilltype") == null || "".equals(map.get("lybilltype"))) throw new BusinessException("由友费控系统生成的单据,在【单据生成】节点中来源单据类型不允许为空!");
	}
	

	/**
	 * 检查单据生成节点 单据信息是否齐全
	 * @param map 通过凭证关联查询出来的 单据生成节点信息
	 * @throws BusinessException
	 */
	protected void checkDefdocParam(Map<String,Object> map) throws BusinessException{
		if(map.get("listtype") == null || "".equals(map.get("listtype"))) 
			throw new BusinessException("请在【自定义档案维护-全局】节点维护,档案编码【YFKANDHRP01】简称中维护对应的信息，具体如何维护查看【备注】描述");
		if(map.get("attachtype") == null || "".equals(map.get("attachtype"))) 
			throw new BusinessException("请在【自定义档案维护-全局】节点维护,档案编码【YFKANDHRP01】助记码中维护对应的信息，具体如何维护查看【备注】描述");
		if(map.get("printcode") == null || "".equals(map.get("printcode")))
			throw new BusinessException("请在【自定义档案维护-全局】节点维护,档案编码【YFKANDHRP01】中维护-友费控打印模板编码");

	}
	/**
	 * 构建自定义档案查询SQL
	 * @param defCode      档案编码
	 * @param defListCode  用户定义档案编码
	 * @return
	 * @throws BusinessException
	 */
	protected String buildDefdocSQL(Object defCode,Object defListCode) throws BusinessException{
		StringBuilder sql = new StringBuilder();
		sql.append(" select ");
		sql.append(" bd_defdoc.code, bd_defdoc.name, bd_defdoc.SHORTNAME listtype, bd_defdoc.def1 attachtype, bd_defdoc.def2 printcode ");
		sql.append(" from bd_defdoc ");
		sql.append(" left join bd_defdoclist on bd_defdoc.pk_defdoclist = bd_defdoclist.pk_defdoclist ");
		sql.append(" left join org_orgs on org_orgs.pk_org = bd_defdoc.pk_org ");
		sql.append(" where bd_defdoc.dr = 0 ");
		sql.append("  and bd_defdoc.enablestate = 2 ");
		sql.append("  and bd_defdoclist.dr = 0 ");
		sql.append("  and org_orgs.dr = 0 ");
		sql.append("  and bd_defdoclist.code='"+defListCode+"' ");
		sql.append("  and bd_defdoc.code = '"+defCode+"'");
		return sql.toString();
	}
	
	
	public IBIPAttachService getBIPAttachService() {
		if(null == this.bipAttachService){
			this.bipAttachService = NCLocator.getInstance().lookup(IBIPAttachService.class);
		}
		return this.bipAttachService;
	}
	public BaseDAO getBaseDAO() {
		return this.baseDAO == null ? new BaseDAO() : this.baseDAO;
	}

	public IYFKService getYFKService() {
		if(null == this.YFKService){
			this.YFKService = NCLocator.getInstance().lookup(IYFKService.class);
		}
		return this.YFKService;
	}
	public ISysInitQry getSysInitQry() {
		if(null == this.sysInitQry){
			this.sysInitQry = NCLocator.getInstance().lookup(ISysInitQry.class);
		}
		return this.sysInitQry;
	}

}
